﻿/******************************************************************************
* File description: CustomComboBox.qml
* Function: 自定义下拉菜单
* Current Version: 1.0.0
 *****************************************************************************/
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Controls.impl 2.14
import QtGraphicalEffects 1.14

Item {
    id: root

    /** 想改width请改editWidth和titleWidth, 不要改width，不然我也不知道会发生什么0w0
     ** editWidth: 文本框的宽度 默认180
     ** titleWidth: 文本框前面提示文字(title)的宽度，如果没设置默认是0 **/


    // public ================================================================================

    // 数据
    property var    model: []
    property string appendText: ""
    property string text: {
        if(index === -1)  return ""
        if(index === -2)  return appendText
        if(model.length <= index){
            return ""
        }
        return model[index]
    }
    property int    index: 0

    property bool   showClearButton: false           // 有内容时，显示清空按钮，index设为-1，会触发clickIndex

    // 内容变更信号（只要变了就触发
    signal          currentIndex(int index)          // 当前下标 [-1]未选择 [-2]用户自定义
    signal          currentText(string text)         // 当前文本
    // 内容变更信号（用户通过点击才触发
    signal          clickIndex(int index)
    signal          clickText(string text)

    onTextChanged: {
        currentIndex(root.index)
        currentText(root.text)
    }

    function onButtonClearText(){
        index = -1
        clickIndex(index)
        clickText(text)
    }

    // 基本样式
    property real   fontsize: config.fontsize

    // 文本框样式
    property int    editWidth: 180*dp
    property int    editHeight: 40*dp
    property string editBgColor: "#FFF"
    property string editBorderColor: "#CCCCCC"
    property color  editBorderHighlightColor: config.themeColor
    property int    editBorderWidth: 1
    property int    editRadius: 3*dp
    property int    editLeftPadding: 10*dp
    property string editFontColor: "#222"
    property var    editFontHorAlign: Text.AlignLeft
    property bool   editHighlightEnabled: true      // 是否选中高亮
    property string editDefaultText: ""    // 当index为-1时，combobox上显示的默认文字

    // 文本可编辑
    property bool   textEditable: false    // 是否可更改默认的ComboModel
    property int    inputMaximumLength: 10000


    // indicator
    property int    indicatorPadding: 35*dp     // 一个不太有用的变量

    // popup
    property real   maxPopupListCount: 4     // 一个页面要展示的最大Item数
    property real   popupItemHeight: 40*dp   // 单个Item高度
    property real   popupHeight: model.length < maxPopupListCount ? popupItemHeight * model.length : popupItemHeight * maxPopupListCount     // popup高度

    property real   popupBorderWidth: 1
    property color  popupBorderColor: "#07111111"
    property real   popupRadius: 3*dp
    property real   popupTopMargin: 2*dp
    property real   popupLeftPadding: 10*dp

    property color  popupItemBgColor: "#FFF"
    property color  popupItemFontColor: "#333"
    property color  popupItemHighlightColor: config.themeColor_light2
    property color  popupItemHighlightedFontColor: config.themeColor_deep

    property bool   popupVisible: control.popup.visible

    // 标题 默认显示在文本框左侧 title=""时无标题
    property string title: ""
    property color  titleColor: "#000"
    property int    titleWidth: title==="" ? 0 : (titleDirect===0 ? 80*dp : editWidth)
    property int    titleHeight: title==="" ? 0 : (titleDirect===0 ? 40*dp : 30*dp)
    property int    titleDirect: 0          // 标题文字位置 0左边 1上边
    property var    titleHAlign: Text.AlignRight       // 标题水平对齐方式
    property var    titleVAlign: Text.AlignVCenter     // 标题垂直对齐方式
    property bool   titleAlignJustify: true           // 标题是否两端对齐（设置为true时会覆盖titleHAline属性！！！）
    property bool   required: false
    property bool   enabled: true


    function setText(changedText){
        // (1) 判断当前设置的内容是否在model里面，是则返回index
        for(let i = 0; i < model.length; i ++){
            if(model[i] === changedText){
                index = i
                return i
            }
        }
        // (2) 传入为空，index置为-1
        if(changedText === ""){
            index = -1
            return -1
        }
        // (3) 传入其他值，设为appendText
        setIndex(-2)
        appendText = changedText
        return -2
    }

    function setIndex (changedIndex) {
        index = changedIndex
    }
    function getText(){
        return text
    }
    function getIndex(){
        return index
    }

    // private ==================================================================================================

    width: titleDirect === 0 ? (titleWidth + editWidth) : editWidth
    height: titleDirect===0 ? editHeight : (titleHeight + editHeight)
    property bool mutex: false

    property var indicatorDelegate: Item {
        width: 35*dp; height: editHeight
        x: editWidth - width
        Image {
            anchors.centerIn: parent
            width: 25*dp
            height: 20*dp
            source: (showClearButton && index!==-1) ? "qrc:/picture/customBoxClearIcon.png" : "qrc:/picture/downarrow.png"
        }
    }


    // 标题
    Item{
        id: rectTitle
        height: titleHeight;    width: titleWidth - 16*dp
        Text{
            text: {
                if(!titleAlignJustify) return title
                else{
                    if(text_rawTitle.contentWidth === 0 || text_space.contentWidth === 0){
                        return   title
                    }
                    return funcTools.justifyAlignAppendSpace(title, parent.width, text_rawTitle.width, text_space.width)
                }
            }
            font.pixelSize: config.fontsize
            anchors.fill: parent
            color: titleColor
            verticalAlignment: titleVAlign
            horizontalAlignment: titleAlignJustify ? Text.AlignHCenter : titleHAlign
        }
        Text{           // 固定在左边的星号
            visible: required
            text: '<font color="#FF0000"">* </font>'
            x: -10*dp
            font.pixelSize: config.fontsize
            height: titleHeight
            width: 10*dp
            verticalAlignment: Text.AlignVCenter
        }

    }
    Text{           // 用来计算空格的长度
        id: text_space
        text: " "
        font.pixelSize: config.fontsize
        visible: false
    }
    Text{           // 用来计算纯文本的长度
        id: text_rawTitle
        text: title
        font.pixelSize: config.fontsize
        visible: false
    }

    ComboBox {
        id: control
        height: editHeight
        width: editWidth
        x: titleDirect===0 ? titleWidth : 0
        y: titleDirect===0 ? 0 : titleHeight
        model: root.model
        padding: 0

        // Popup中每一个选项的代理样式
        delegate: ItemDelegate {
            width: control.width
            height: popupItemHeight
            leftPadding: popupLeftPadding
            background: Rectangle {
                property bool isHover: false
                color: (root.index === index || isHover) ? popupItemHighlightColor : popupItemBgColor
                MouseArea{
                    anchors.fill: parent
                    hoverEnabled: true
                    onEntered: {
                        parent.isHover = true
                    }onExited: {
                        parent.isHover = false
                    }
                    onClicked: {
                        root.index = index
                        popup.visible = false
                        clickIndex(index)
                        clickText(root.text)
                    }
                }
            }

            // 每个代理选项样式
            contentItem: Text {
                text: modelData
                color: root.index === index ? popupItemHighlightedFontColor : popupItemFontColor
                font.pixelSize: fontsize
                elide: Text.ElideRight
                verticalAlignment: Text.AlignVCenter
            }
            highlighted: root.index === index
        }
        // 显示框文本样式
        contentItem: TextInput {
            id: textInput
            font.pixelSize: fontsize
            color: editFontColor
            text: root.text
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: editFontHorAlign
            leftPadding: editLeftPadding
            rightPadding: indicatorPadding
            maximumLength: root.inputMaximumLength
            clip: true
            selectByMouse: true //设置为可以被鼠标选中
            onTextChanged: {
                textInput.cursorPosition = 0
            }
            Component.onCompleted: {
                textInput.cursorPosition = 0
            }
            onWidthChanged: {
                textInput.cursorPosition = 0
            }

            Rectangle{                      // 没有内容时显示的内容……
                height: parent.height - 2
                width: parent.width - 2
                x: 1; y: 1
                radius: root.editRadius
                visible: root.text === ""
                Text{
                    x: editLeftPadding
                    anchors.verticalCenter: parent.verticalCenter
                    text: editDefaultText
                    font.pixelSize: fontsize
                }
            }
        }

        // 显示框背景样式
        background: Rectangle {

            anchors.fill: parent
            color: editBgColor
            border.width: editBorderWidth
            border.color: (this.isHovered || control.popup.visible || textInput.focus) ? editBorderHighlightColor : editBorderColor
            radius: editRadius
            property bool isHovered: false
            MouseArea{      // Hover样式
                anchors.fill: parent
                propagateComposedEvents: true
                hoverEnabled: config.hoverEnabled
                cursorShape: Qt.IBeamCursor
                onEntered: {
                    parent.isHovered = true && config.hoverEnabled
                }onExited: {
                    parent.isHovered = false
                }onPressed:{
                    mouse.accepted = false
                }onReleased:{
                    mouse.accepted = false
                }
            }
            CustomTooltip{
                visible: parent.isHovered && textInput.contentWidth > editWidth-editLeftPadding-indicatorPadding
                text: root.text
            }
            // 阴影
            layer.enabled: control.popup.visible && editHighlightEnabled && config.device!==2
            layer.effect: DropShadow {
                visible: editHighlightEnabled
                radius: 12*dp
                samples: 43
                transparentBorder: true
                color: editBorderHighlightColor
                opacity: 0.3
            }
        }

        // 向下三角箭头
        indicator: Item {
            width: 35*dp; height: editHeight
            x: editWidth - width
            Image {
                anchors.centerIn: parent
                width: 25*dp
                height: 20*dp
                source: (showClearButton && index!==-1) ? "qrc:/picture/customBoxClearIcon.png" : "qrc:/picture/downarrow.png"
            }
        }

        // 下拉框（Popup）
        popup: Popup {
            id: popup
            width: control.width
            height: popupHeight
            y: control.height + popupTopMargin
            padding: 0
            // popup的内容
            contentItem: ListView {
                id: listview
                clip: true
//                model: control.popup.visible ? control.delegateModel : null
                model: control.delegateModel
                currentIndex: control.highlightedIndex
            }
            // popup的背景
            background: Rectangle {
                border.color: popupBorderColor
                border.width: popupBorderWidth
                layer.enabled: true
                layer.effect: DropShadow {
                    radius: 21*dp
                    samples: 43
                    transparentBorder: true
                    color: "#4D333333"
                }
            }

            // 过渡效果
            enter: Transition {
                NumberAnimation {
                    property: "height"
                    from: 0
                    to: popupHeight
                    duration: 200
                    easing.type: Easing.InOutQuad
                }
            }
            exit: Transition {
                NumberAnimation {
                    property: "height"
                    from: popupHeight
                    to: 0
                    duration: 200
                    easing.type: Easing.InOutQuad
                }
            }
        }
    }

    Rectangle{      // 禁用状态
        anchors.fill: control
        color: "#EEEEEE"
        opacity: 0.6
        MouseArea{
            anchors.fill: parent
            onReleased: {

            }
        }
        visible: !root.enabled
    }

    Item{
        height: control.height; width: editWidth - indicatorDelegate.width
        x: control.x; y: control.y
        visible: !textEditable
        MouseArea{      // 文本区域的框框
            anchors.fill: parent
            cursorShape: Qt.PointingHandCursor
            onReleased: {
                if(!root.enabled){
                    return
                }
                if(control.popup.visible){
                    control.popup.close()
                }else{
                    control.popup.open()
                }
                control.focus = true
            }
        }
    }
    Item{
        height: control.height; width: indicatorDelegate.width
        x: root.width - width; y: control.y
        MouseArea{     // 下拉箭头的框框
            anchors.fill: parent
            cursorShape: Qt.PointingHandCursor
            onReleased: {
                if(!root.enabled){
                    return
                }
                if(showClearButton&&index!==-1){
                    console.log("点击清空")
                    onButtonClearText()
                }else{
                    console.log("点击下拉")
                    if(control.popup.visible){
                        control.popup.close()
                    }else{
                        control.popup.open()
                    }
                }
                control.focus = true
            }
        }
    }
}
